package timbap.artwork.retrieval;

import timbap.artwork.storage.ResultStorageManager;
import timbap.visualizer.api.model.PlaylistEntry;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class ArtworkRetrievalManager implements ImageResultHandler {

    private ArtworkRetriever artworkRetriever;

    private PlaylistEntry playlistEntry;
    private List<JButton> imageResultButtons;
    private JLabel resultInfoLabel;

    private int validResultsCount = 0;
    private int failedResultsCount = 0;
    private List<String> imageUrls;
    private List<ImageRetrieverThread> imageRetrieverThreads = new ArrayList<ImageRetrieverThread>();
    private int indexOfNextImageUrl;

    public ArtworkRetrievalManager(PlaylistEntry pPlaylistEntry,
                                   List<JButton> pImageResultButtons,
                                   final JLabel pResultInfoLabel,
                                   ArtworkRetriever pArtworkRetriever) {
        resultInfoLabel = pResultInfoLabel;
        artworkRetriever = pArtworkRetriever;
        playlistEntry = pPlaylistEntry;
        imageResultButtons = pImageResultButtons;
    }

    public void imageResultFound(final InputStream pImageDataFromHttp) {
        addResult(pImageDataFromHttp);
        updateResultsInfo();
    }

    public void imageRetrievalFailed() {
        failedResultsCount++;
        tryNextImageUrl();
        updateResultsInfo();
    }

    private void reset() {
        resultInfoLabel.setText("");
        for (JButton tImageResultButton : imageResultButtons) {
            tImageResultButton.setIcon(null);
            tImageResultButton.setEnabled(false);
        }
        for (ImageRetrieverThread tImageRetrieverThread : new ArrayList<ImageRetrieverThread>(imageRetrieverThreads)) {
            if (!tImageRetrieverThread.isDone()) {
                tImageRetrieverThread.stop();
            }
            imageRetrieverThreads.remove(tImageRetrieverThread);
        }
        indexOfNextImageUrl = 0;
        validResultsCount = 0;
        failedResultsCount = 0;
    }

    private void updateResultsInfo() {
        int tAliveImageRetrievers = 0;
        for (ImageRetrieverThread tImageRetrieverThread : new ArrayList<ImageRetrieverThread>(imageRetrieverThreads)) {
            if (!tImageRetrieverThread.isDone()) {
                tAliveImageRetrievers++;
            } else {
                imageRetrieverThreads.remove(tImageRetrieverThread);
            }
        }
        if (tAliveImageRetrievers == 0) {
            resultInfoLabel.setText("Finished.");
        } else {
            resultInfoLabel.setText("<html>Found " + imageUrls.size() + " results. Retrieving ...<br/>"
                    + "(" + validResultsCount + " valid, " + failedResultsCount + " failed)"  + " ...</html>");
        }

    }

    private synchronized void tryNextImageUrl() {
        if (imageUrls != null && indexOfNextImageUrl < imageUrls.size()) {
            String tNextImageUrl = imageUrls.get(indexOfNextImageUrl);
            ImageRetrieverThread tRetrieverThread = new ImageRetrieverThread(tNextImageUrl, this, artworkRetriever);
            tRetrieverThread.start();
            imageRetrieverThreads.add(tRetrieverThread);
            indexOfNextImageUrl++;
        }
    }

    private synchronized void addResult(InputStream tImageDataFromHttp) {
        if (validResultsCount < 5 && tImageDataFromHttp != null) {
            ResultStorageManager tStorageManager = ResultStorageManager.getInstance();
            boolean tFileWritten = tStorageManager.writeToTempDir(tImageDataFromHttp, playlistEntry, validResultsCount);
            if (tFileWritten) {
                InputStream tImageDataFromTempFile = tStorageManager.loadFromTempDir(playlistEntry, validResultsCount);
                try {
                    BufferedImage tBufferedImage = ImageIO.read(tImageDataFromTempFile);
                    if (tBufferedImage != null) {
                        JButton tResultButton = imageResultButtons.get(validResultsCount);
                        tResultButton.setIcon(new ImageIcon(
                                tBufferedImage.getScaledInstance(100, -1, Image.SCALE_SMOOTH)));
                        tResultButton.setEnabled(true);
                        validResultsCount++;
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    public void performQuery(String pQueryTerms) {
        if (pQueryTerms != null && pQueryTerms.length() > 0) {

            reset();
            imageUrls = artworkRetriever.performSearch(pQueryTerms);

            if (imageUrls.size() > 0) {
                resultInfoLabel.setText("<html>Found " + imageUrls.size() + " results. Retrieving ...<br/></html>");
            } else {
                resultInfoLabel.setText("No images found.");
            }
            for (int i=0; i < Math.min(imageUrls.size(), 5); i++) {
                ImageRetrieverThread tRetrieverThread =
                        new ImageRetrieverThread(imageUrls.get(i), this, artworkRetriever);
                tRetrieverThread.start();
                imageRetrieverThreads.add(tRetrieverThread);
                indexOfNextImageUrl++;
            }
        }
    }
}
